package com.sdy.supermarket.biz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sdy.approval.api.ApprovalAllApi;
import com.sdy.common.constant.Constants;
import com.sdy.common.model.BizException;
import com.sdy.common.utils.Assert;
import com.sdy.common.utils.DateUtil;
import com.sdy.common.utils.RandomUtil;
import com.sdy.common.utils.StringUtil;
import com.sdy.mq.service.MqProducerService;
import com.sdy.redis.service.RedisService;
import com.sdy.supermarket.biz.constants.MqConstants;
import com.sdy.supermarket.biz.constants.RedisConstants;
import com.sdy.supermarket.biz.model.GsOrder;
import com.sdy.supermarket.biz.model.GsOrderApp;
import com.sdy.supermarket.biz.model.GsOrderItem;
import com.sdy.supermarket.biz.model.GsRes;
import com.sdy.supermarket.biz.model.GsSelfSystem;
import com.sdy.supermarket.biz.model.GsUserApply;
import com.sdy.supermarket.biz.service.ApplyService;
import com.sdy.supermarket.biz.service.GsOrderAppService;
import com.sdy.supermarket.biz.service.GsOrderItemService;
import com.sdy.supermarket.biz.service.GsOrderService;
import com.sdy.supermarket.biz.service.GsResService;
import com.sdy.supermarket.biz.service.GsSelfSystemService;
import com.sdy.supermarket.biz.service.GsUserApplyService;
import com.sdy.usercenter.api.UserQueryApi;
import com.sdy.usercenter.api.dto.UserDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Array;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ApplyServiceImpl implements ApplyService {
    @Autowired
    private GsOrderService gsOrderService;
    @Autowired
    private GsOrderItemService gsOrderItemService;
    @Autowired
    private GsResService gsResService;
    @Autowired
    private GsOrderAppService gsOrderAppService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private ApprovalAllApi approvalAllApi;
    @Autowired
    private UserQueryApi userQueryApi;


    @Override
    public String newApply(GsOrder gsOrder) throws Exception {
        Assert.isTrue(gsOrder.getItemList() == null || gsOrder.getItemList().isEmpty(), "未选择产品！");
        Date now = new Date();
        UserDTO user = userQueryApi.getUser(gsOrder.getUserId());
        gsOrder.setCreateTime(now).setOrderNo(generateOrderNo()).setDeptId(user.getOwnDeptId());
        Assert.isBlank(gsOrder.getContactName(), "未填写联系人");
        Assert.isBlank(gsOrder.getContactTel(), "未填写联系方式");
        Assert.isNull(gsOrder.getDeptType(), "未选择部门");
        gsOrderService.save(gsOrder);
        List<Integer> itemIdList = gsOrder.getItemList().stream().map(GsOrderItem::getId).collect(Collectors.toList());
        Collection<GsOrderItem> itemList = gsOrderItemService.listByIds(itemIdList);
        Assert.isTrue(itemList.size() != gsOrder.getItemList().size(), "产品数据不正确");
        Collection<GsRes> resList = gsResService.listByIds(
                itemList.stream().map(GsOrderItem::getResId).collect(Collectors.toList()));
        // 校验用户是否已经申请过该资源
        List<GsOrderItem> existOrderItemList = gsOrderItemService.lambdaQuery()
                .isNotNull(GsOrderItem::getOrderId)
                .eq(GsOrderItem::getType, 1)
                .in(GsOrderItem::getResId, resList.stream().map(GsRes::getId).collect(Collectors.toList()))
                .notIn(GsOrderItem::getState, Arrays.asList(5, 7))
                .eq(GsOrderItem::getUserId, gsOrder.getUserId())
                .select(GsOrderItem::getId, GsOrderItem::getResId)
                .list();
        if (!existOrderItemList.isEmpty()) {
            Collection<GsRes> errResList = gsResService.listByIds(existOrderItemList.stream().map(GsOrderItem::getResId).collect(Collectors.toList()));
            Assert.isTrue(true, String.format("资源 %s 已经申请过了", errResList.stream().map(GsRes::getName).collect(Collectors.toList()).toString()));
        }
        // 是否需要自建系统
        boolean needApp = resList.stream().anyMatch(item -> !item.getType().equals(2));
        Assert.isTrue(needApp && CollectionUtils.isEmpty(gsOrder.getAppList()), "未选择自建系统");
        for (GsOrderItem item : itemList) {
            Assert.isNull(item.getResId(), "产品数据错误！");
            Assert.isTrue(!gsOrder.getUserId().equals(item.getUserId()), "产品数据错误！");
            gsOrderItemService.updateById(new GsOrderItem()
                    .setId(item.getId())
                    .setType(1)
                    .setState(2)
                    .setOrderItemNo(gsOrder.getOrderNo().concat("-").concat(item.getId().toString()))
                    .setDeptType(gsOrder.getDeptType())
                    .setContactName(gsOrder.getContactName())
                    .setContactTel(gsOrder.getContactTel())
                    .setRemark(gsOrder.getRemark())
                    .setOrderNo(gsOrder.getOrderNo())
                    .setOrderId(gsOrder.getId())
                    .setIpIdList(gsOrder.getIpIdList())
                    .setEnclosure(gsOrder.getEnclosure())
                    .setDeptId(user.getOwnDeptId())
            );
        }
        // 自建系统相关操作
        if (needApp) {
            for (GsOrderApp app : gsOrder.getAppList()) {
                String ips = app.getIp();
                Assert.isBlank(app.getAppCode(), "未选择自建系统code");
                Assert.isBlank(ips, "未选择自建系统ip");
                for (String s : ips.split(",")) {
                    Assert.isTrue(!Pattern.matches(Constants.REGEX_IPV4, s), "ip格式错误");
                }
                // 将自建系统插入到拆分出来的订单中
                for (GsOrderItem item : itemList) {
                    gsOrderAppService.save(new GsOrderApp()
                            .setAppCode(app.getAppCode())
                            .setIp(app.getIp())
                            .setOrderId(gsOrder.getOrderNo().concat("-").concat(item.getId().toString()))
                            .setCreateTime(new Date()));
                }
            }
        }
        return gsOrder.getOrderNo();
    }

    @Override
    public int updateOrder(GsOrderItem gsOrderItem) throws BizException {
        // 修改时修改拆分出来的订单信息
        gsOrderService.update(Wrappers.<GsOrder>lambdaUpdate().eq(GsOrder::getOrderNo, gsOrderItem.getOrderNo()).set(GsOrder::getModifyTime, new Date()));
        Assert.isBlank(gsOrderItem.getContactName(), "未填写联系人");
        Assert.isBlank(gsOrderItem.getContactTel(), "未填写联系方式");
        Assert.isNull(gsOrderItem.getDeptType(), "未选择部门");
        gsOrderItem.setState(3);
        boolean updateById = gsOrderItemService.updateById(gsOrderItem);
        List<GsOrderApp> appList = gsOrderItem.getAppList();
        // 删除该订单已有的自建系统
        boolean removeByIds = gsOrderAppService.remove(Wrappers.<GsOrderApp>lambdaQuery().eq(GsOrderApp::getOrderId, gsOrderItem.getOrderItemNo()));
        for (GsOrderApp app : appList) {
            String ips = app.getIp();
            Assert.isBlank(app.getAppCode(), "未选择自建系统code");
            Assert.isBlank(ips, "未选择自建系统ip");
            for (String s : ips.split(",")) {
                Assert.isTrue(!Pattern.matches(Constants.REGEX_IPV4, s), "ip格式错误");
            }
            gsOrderAppService.save(new GsOrderApp()
                    .setAppCode(app.getAppCode())
                    .setIp(app.getIp())
                    .setOrderId(gsOrderItem.getOrderItemNo())
                    .setCreateTime(new Date()));
        }
        Boolean flow = approvalAllApi.updateFlow(gsOrderItem.getOrderItemNo(), gsOrderItem.getUserId());
        Assert.isTrue(!updateById || !removeByIds || !flow, "修改订单时系统出现错误,请重试");
        return 1;
    }

    @Override
    public void newOrder(GsOrderItem gsOrderItem) throws BizException {
        GsRes res = gsResService.getById(gsOrderItem.getResId());
        gsOrderItem.setResName(res.getName());
        List<GsOrderItem> list = gsOrderItemService.list(Wrappers.<GsOrderItem>lambdaQuery().eq(GsOrderItem::getResId, gsOrderItem.getResId()).eq(GsOrderItem::getUserId, gsOrderItem.getUserId()));
        Assert.isTrue(!list.isEmpty(), "该资源已存在于购物车或者已经申请过该资源");
        gsOrderItemService.save(gsOrderItem.setCreateTime(new Date()).setOrderId(null).setIsDone(0)
                .setType(2).setState(0).setContactName("").setContactTel("").setRemark(""));
    }

    @Override
    public void removeOrderItem(List<Integer> orderItemIdList, Integer userId, Boolean checked) throws BizException {
        if (checked) {
            gsOrderItemService.remove(
                    new LambdaQueryWrapper<GsOrderItem>()
                            .eq(GsOrderItem::getUserId, userId)
                            .in(!CollectionUtils.isEmpty(orderItemIdList), GsOrderItem::getId, orderItemIdList)
            );
        } else {
            Collection<GsOrderItem> itemList = gsOrderItemService.listByIds(orderItemIdList);
            if (itemList.stream().anyMatch(item -> !item.getUserId().equals(userId))) {
                throw new BizException("没有订单访问权限");
            }
            gsOrderItemService.removeByIds(orderItemIdList);
        }
    }

    @Override
    public void submitOrder(List<Integer> orderItemIdList, Integer userId) throws BizException {
        Assert.isTrue(orderItemIdList == null || orderItemIdList.isEmpty(), "请选择应用");
        Collection<GsOrderItem> itemList = gsOrderItemService.listByIds(orderItemIdList);
        if (itemList.stream().anyMatch(item -> !item.getUserId().equals(userId))) {
            throw new BizException("没有订单访问权限");
        }
        if (itemList.stream().anyMatch(item -> item.getOrderId() != null || !item.getType().equals(2))) {
            throw new BizException("订单状态不正确");
        }

        Collection<GsRes> resList = gsResService.listByIds(
                itemList.stream().map(GsOrderItem::getResId).collect(Collectors.toList()));
        // 校验用户是否已经申请过该资源
        List<GsOrderItem> existOrderItemList = gsOrderItemService.lambdaQuery()
                .isNotNull(GsOrderItem::getOrderId)
                .eq(GsOrderItem::getType, 1)
                .in(GsOrderItem::getResId, resList.stream().map(GsRes::getId).collect(Collectors.toList()))
                .notIn(GsOrderItem::getState, Arrays.asList(5, 7))
                .eq(GsOrderItem::getUserId, userId)
                .select(GsOrderItem::getId, GsOrderItem::getResId)
                .list();
        if (!existOrderItemList.isEmpty()) {
            Collection<GsRes> errResList = gsResService.listByIds(existOrderItemList.stream().map(GsOrderItem::getResId).collect(Collectors.toList()));
            Assert.isTrue(true, String.format("资源 %s 已经申请过了", errResList.stream().map(GsRes::getName).collect(Collectors.toList()).toString()));
        }

        gsOrderItemService.update(new GsOrderItem().setState(0),
                new LambdaQueryWrapper<GsOrderItem>()
                        .notIn(GsOrderItem::getId, orderItemIdList)
                        .isNull(GsOrderItem::getOrderId)
                        .eq(GsOrderItem::getUserId, userId)
                        .eq(GsOrderItem::getType, 2));
        gsOrderItemService.update(new GsOrderItem().setState(1),
                new LambdaQueryWrapper<GsOrderItem>()
                        .in(GsOrderItem::getId, orderItemIdList)
                        .isNull(GsOrderItem::getOrderId)
                        .eq(GsOrderItem::getUserId, userId)
                        .eq(GsOrderItem::getType, 2));
    }

    /**
     * 生成订单号
     */
    private String generateOrderNo() {
        String orderNoKey = "order_no_serial";
        String timeStr = DateUtil.getDate("yyyyMMddHHmmss");
        String key = RedisConstants.REDIS_PREFIX + orderNoKey + timeStr;
        long r = redisService.incr(key);
        redisService.expire(key, 5);
        return DateUtil.getDate("yyyyMMddHHmmss")
                .concat("01")
                .concat(String.format("%02d", r))
                .concat(RandomUtil.produceNumber(2));
    }
}
